<?php

class MySQL {
    
    protected $connection;
    protected $queries;
    protected $query;
    protected $quoteString;
    protected $errors;
    
    private static $instance;

   protected function isDebugMode() {
       return (defined('DB_DEBUG') && DB_DEBUG == true);
   }
   
   protected function riseError($oException) {
       $this->errors[] = $oException;
       if ($this->isDebugMode()) {
           echo $oException;
       }
   }
   
   private function __construct() {
   	//
   }
   
   public static function getInstance() {
      if (!isset(self::$instance)) {
           $class = __CLASS__;
           $instance = self::$instance = new $class;
           try {
                $instance->connect();
            if($instance->getDefaultDb() != '') {
                $instance->selectDefaultDb();
            }
           } catch (Exception $e) {
               $instance->riseError($e);
           }
       }
       return self::$instance;
   }

   
   protected function logQuery($sSql) {
       $this->queries[] = $sSql;
   }
   
   public function &sql($sSql) {
       $this->query = $sSql;
       return $this;
   }
   
   public function &bind($params = null) {
        $joinstr   = array();
        $countpars = 1;
        $query = $this->query;
        $sLabel = chr(0) . chr(1);
        $parsed_query = $query;
        
        if ( !is_array($params) || (func_num_args() > 1) ){
            $params    = func_get_args();
            $countpars = func_num_args();
        } 
        if (!isset($params)){
            $countpars = 0;
            $params    = array();
        } 
        
        if(is_array($params) && count($params) > 0 && 
                preg_match_all("/\:([0-9]{1,3}|\[[0-9]{1,3}\].)/", $query, $patterns))
        {
            $patterns = array_unique($patterns[1]);
            $parsed_query = preg_replace("/(\:)([0-9]{1,3}|\[[0-9]{1,3}\].)/", "\\1" . $sLabel . "\\2" . $sLabel, $query);
            foreach ($patterns as $key) {
                if(!empty($key) && $key[0]=='['){
                    //arrays keys
                    $realnum   = substr($key, 1, -2);
                    $lastchar  = $key[ strlen($key) - 1 ];
                    $quotechar = strpos("\"'", $lastchar) === false ? '' : $lastchar;
                    if($countpars == 1 && count($patterns) == 1){
                        if ($realnum == 0){
                            $joinstr[$realnum] = join($quotechar . "," . $quotechar, array_map(array(&$this, 'quoteString'), $params));
                            $parsed_query = str_replace(":" . $sLabel . $key . $sLabel, $joinstr[$realnum] . $lastchar, $parsed_query);
                        }   
                    } else {
                        if (!isset($params[$realnum])) $params[$realnum] = array();
                        else if (!is_array($params[$realnum])) $params[$realnum] = array($this->quoteString($params[$realnum]));
                        else $params[$realnum] = array_map(array(&$this, 'quoteString'), $params[$realnum]);
                        $joinstr[$realnum] = join($quotechar.",".$quotechar, array_map(array(&$this, 'quoteString'), $params[$realnum]));
                        $parsed_query = str_replace(":".$sLabel.$key.$sLabel, $joinstr[$realnum].$lastchar, $parsed_query);
                    }
                } else {
                    //non array keys
                    if (!isset($params[$key]) or is_array($params[$key])) $params[$key] = '';
                    else $params[$key] = $this->quoteString($params[$key]);
                    $parsed_query = str_replace(":" . $sLabel . $key . $sLabel, $params[$key], $parsed_query);
                }
            }
        }
        
        try {
           $oResult =& $this->query($parsed_query);
        } catch (Exception $e) {
           $this->riseError($e);
        }
        
        return $oResult;
   }
      
   public function dumpQueries() {
       foreach ($this->queries as $sSql) {
           echo $sSql . '<br />';
       }
   }
   
   public function dumpErrors() {
       foreach ($this->errors as $sError) {
           echo $sError . '<br />';
       }
   }

    
    public function selectDb($sDb) {
        if(!mysql_select_db($sDb, $this->connection)) {
            //throw new Exception(mysql_error());
        }
    }
    
    protected function quoteString($string) {
        if(is_array($string)) {
            return '';
        } else {
            return mysql_real_escape_string($string);
        }
    }
    
    protected function getDefaultDb() {
        return (defined(strtoupper(__CLASS__) . '_DEFAULT_DB') ? strtoupper(__CLASS__) . '_DEFAULT_DB' : '');
    }
    
    protected function selectDefaultDb() {
        $this->selectDb(constant(strtoupper(__CLASS__) . '_DEFAULT_DB'));
    }
    
    protected function connect() {
        if(!$this->connection = mysql_connect(constant(strtoupper(__CLASS__) . '_HOST'), constant(strtoupper(__CLASS__) . '_USER'), constant(strtoupper(__CLASS__) . '_PASSWORD'))) {
            //throw new Exception(mysql_error());
        }
    }
    
    protected function query($sSql) {
        if(!$oResult = mysql_query($sSql, $this->connection)) {
            //throw new Exception(mysql_error());
        }
        return $oResult;
    }
    
    public function fetchAssoc($oResult) {
        $aRow = mysql_fetch_assoc($oResult);
        return $aRow;
    }
    
    public function identity() {
        $id = mysql_insert_id($this->connection);
		/*
        if($id == 0) {
            throw new Exception('There was no identity has been inserted');
        }
		*/
        return $id;
    }
}
?>